﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using App.Core.Extensions;
using App.Domain;
using App.Web.ViewModels;
using App.Web.Utility;
using AutoMapper;
using System.Text;

namespace App.Web.Controllers
{
    public class CompanyController : BaseController
    {
        private EntityRepository _Repository = new EntityRepository();
		private AppEntities _Context = new AppEntities();
        
		#region Constructors
		public CompanyController()
		{
		}

		public CompanyController(UserViewModel currentUser)
			: base(currentUser)
        {
        }
		#endregion Constructors

		#region Action Methods

        public ActionResult Index()
        {
            return View();
        }
        /// <summary>
        /// Registration GET Request Handler
        /// </summary>
        /// <returns></returns>
        public ActionResult Registration()
        {
            //SessionCache.RegisteringCompanyID = 2;
            //return RedirectToAction("RegistrationSecondStep", new { id = 2 });

            //Change process

            //CompanyViewModel model = new CompanyViewModel();
            //ViewBag.UploadLogoControls = true;
            //ViewBag.PageTitle = "Company Registration";
            //ViewBag.IsRegistrationMode = true;
            //return View("ProfileEdit", model);            

            //New Process
            ContactViewModel viewModel = new ContactViewModel();
            viewModel.CompanyID = 0;
            viewModel.IsDeleted = "False";
            viewModel.User = new UserViewModel();
            viewModel.User.IsActive = false;
            viewModel.User.GroupID = ConfigReader.UserGroupIDOfCompanyAdmin;
            ViewBag.IsRegistrationMode = true;
            return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
        }
        /// <summary>
        /// Registration First Step POST Request handler. 
        /// Creates an Company Entity in the Database
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Registration(ContactViewModel viewModel)
        {
            String companyName = Request.Form["CompanyName"].ToString();
            String email = Request.Form["Email"].ToString();

            //if (!ModelState.IsValid)
            //    return View("ProfileEdit", viewModel);

            if (_Context.IsDuplicateCompanyName(companyName))
            {
                ViewBag.IsRegistrationMode = true;
                ViewBag.CompanyName = companyName;
                ViewBag.Email = email;

                ModelState.AddModelError("DuplicateCompany", "Sorry: This Company Name Already Exists");
                return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
            }
            else if (_Context.IsDuplicateUserName(viewModel.User.UserName, 0))
            {
                ViewBag.IsRegistrationMode = true;
                ViewBag.CompanyName = companyName;
                ViewBag.Email = email;
                
                ModelState.AddModelError("DuplicateUser", "User Name already exists, please choose another.");
                return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
            }

            else if (_Context.IsDuplicateEmail(email))
            {
                ViewBag.IsRegistrationMode = true;
                ViewBag.CompanyName = companyName;
                ViewBag.Email = email;

                ModelState.AddModelError("DuplicateEmail", "Sorry! This Email Already taken, Please choose another.");
                return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
            }
            else
            {
                //viewModel.IsActive = false;

                ///Create a Blank Company and insert it in the database.
                int createdCompanyID = WebUtil.InsertBlankCompany(companyName);

                ///Rebuild the Company Route Cache, and re-map them in the global routing cache
                MvcApplication.RefreshRoutes(true);

                SessionCache.RegisteringCompanyID = createdCompanyID;

                //Add the Contact for the corresponding Company created in step 1.
                int ContactID = WebUtil.InsertInitialContact(email, viewModel.FirstName, viewModel.LastName, createdCompanyID);

                ///Save the User
                User userEntity = new User();
                userEntity = Mapper.Map<UserViewModel, User>(viewModel.User, userEntity);
                userEntity.IsActive = true;
                _Context.AddToUsers(userEntity);
                _Context.SaveChanges();

                ///Save the User Contact Mapping
                UserContact usrContactEntity = new UserContact();
                usrContactEntity.ContactID = ContactID;
                usrContactEntity.UserID = userEntity.ID;
                _Context.AddToUserContacts(usrContactEntity);
                _Context.SaveChanges();

                //Get the newly created company and contact information
                Company company = _Context.Companies.FirstOrDefault(Q => Q.ID == createdCompanyID);
                Contact contact = _Context.Contacts.FirstOrDefault(Q => Q.ID == ContactID);

                //Send mail to the customer with the comany activation link
                sendActivationNotification(company,contact);
                //Send mail to the Admin about a new customer registration
                sendAdminNotification(company);

                return RedirectToAction("RegistrationSuccess");
            }

            //return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
        }

        /// <summary>
        /// Registration Second Step GET Request Handler
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public ActionResult RegistrationSecondStep()
        {
            int companyID = SessionCache.RegisteringCompanyID;
            if (companyID == 0)
                return RedirectToAction("Registration");
            else
            {                
                ContactViewModel viewModel = new ContactViewModel();
                viewModel.CompanyID = companyID;
                viewModel.IsDeleted = "False";
                viewModel.User = new UserViewModel();
                viewModel.User.IsActive = false;
                viewModel.User.GroupID = ConfigReader.UserGroupIDOfCompanyAdmin;
                ViewBag.IsRegistrationMode = true;
                return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
            }
        }
        /// <summary>
        /// Registration Second Step Post Back Handler
        /// </summary>
        /// <param name="viewModel"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult RegistrationSecondStep(ContactViewModel viewModel)
        {
            if (!ModelState.IsValid)
                return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
            else if (_Context.IsDuplicateEmail(viewModel.EmailOffice))
                ModelState.AddModelError("", "Office Email already taken, please choose another.");
            else if (_Context.IsDuplicateEmail(viewModel.EmailPersonal))
                ModelState.AddModelError("", "Personal Email already taken, please choose another.");
            else if(_Context.IsDuplicateUserName(viewModel.User.UserName, 0))
                ModelState.AddModelError("", "User Name already exists, please choose another.");
            else if (!_Context.IsValidRegistrationRequest(viewModel.CompanyID))
                ModelState.AddModelError("", "Invalid Request");
            else
            {
                ///Save Contact
                Contact entity = new Contact();
                entity = Mapper.Map<ContactViewModel, Contact>(viewModel, entity);                
                _Context.AddToContacts(entity);
                _Context.SaveChanges();

                ///Save the User
                User userEntity = new User();
                userEntity = Mapper.Map<UserViewModel, User>(viewModel.User, userEntity);                
                _Context.AddToUsers(userEntity);
                _Context.SaveChanges();

                ///Save the User Contact Mapping
                UserContact usrContactEntity = new UserContact();
                usrContactEntity.ContactID = entity.ID;
                usrContactEntity.UserID = userEntity.ID;
                _Context.AddToUserContacts(usrContactEntity);
                _Context.SaveChanges();
                
                //TODO: Send Email Notification with the Activation Link
                //sendMailToAdmin();
                ////And Another email notification to the Site Admin 
                //sendMailToUser();

                //Company company = _Context.Companies.FirstOrDefault(P => P.ID == entity.CompanyID);
                //sendActivationNotification(company, entity);
                //sendAdminNotification(company);

                return RedirectToAction("RegistrationSuccess");
            }
            ViewBag.IsRegistrationMode = true;
            return View("~/Areas/Private/Views/Contact/Edit.cshtml", viewModel);
        }

        

        public ActionResult ActivateStore(int storeID = 0, string activationKey = "")
        {
            Company company = _Context.Companies.FirstOrDefault(Q => Q.ID == storeID && Q.ActivationKey == new Guid(activationKey));
            company.IsActive = true;

            _Context.SaveChanges();

            ViewBag.RegType = "Activation";
            return View("RegistrationSuccess");
            //return View("~/Company/RegistrationSuccess.cshtml");
            //return RedirectToAction("ActivateStore");
        }

        public ActionResult RegistrationSuccess()
        {
            ViewBag.RegType = "SaveStore";
            SessionCache.RegisteringCompanyID = 0;
            return View();
        }

        #endregion Action Methods

        #region Action Methods of Company Portal

        public ActionResult List()
        {
            var query = from P in _Context.Companies.Include("District.Country") where P.IsActive orderby P.Name select P;
            ViewData[AppConstants.ViewDataKeys.COMPANY_LIST] = query == null ? new List<Company>() : query.ToList();
            return View();
        }

        public ActionResult Details(String companyKey)
        {
            Company company = _Context.Companies.Include("IndustryType").FirstOrDefault(P => String.Compare(P.CompnayUrl, companyKey, true) == 0);
            if (company != null)
            {
                UtilityDAO dao = new UtilityDAO();
                DbParameter[] parameters = new[]{
                    new DbParameter("@CompanyID", company.ID),
                    new DbParameter("@RecordToReturn", 5)
                };
                System.Data.DataSet topViewedProducts = dao.GetDataSet(DbObject.SP.GET_TOP_VIEWED_PRODUCTS, parameters, true);
                ViewData[AppConstants.ViewDataKeys.TOP_VIEWED_PRODUCTS] = topViewedProducts;
                ViewData[AppConstants.ViewDataKeys.COMPANY_KEY] = company.CompnayUrl;

                System.Data.DataSet recentProducts = dao.GetDataSet(DbObject.SP.GET_RECENT_PRODUCTS, parameters, true);
                ViewBag.DataSource = recentProducts.Tables[0];
                ViewBag.TotalRecord = recentProducts.Tables[0].Rows.Count;
                ViewBag.ShowEditLink = false;
            }
            return View(company);
        }

        //TODO: This method is obsolete and needs to be removed after making few adjustments in /product/details action method.
        /// <summary>
        /// This Method is obsolete and needs to be reomoved, as this action method is routed to the /product/details controller.
        /// And its properties should be implementd there.
        /// </summary>
        /// <param name="companyKey"></param>
        /// <param name="productID"></param>
        /// <param name="productKey"></param>
        /// <returns></returns>
        public ActionResult ProductDetails(String companyKey, String productID, String productKey)
        {
            ProductViewModel product = null;
            Product entity = _Repository.GetProductByID(productID.ToInt());
            if (entity != null)
            {
                ///Check if this is correct URL, otherwise redirect to the correct Product URL 
                ///with the HTTP Status code 301 (Moved Permanently) 
                ///Important for SEO
                if (String.Compare(entity.ProductUrl, productKey, true) != 0)
                {
                    return RedirectToRoutePermanent(AppConstants.RouteNames.Public.COMPANY_PRODUCT_DETAILS, new {CompanyKey = companyKey, ProductID = productID, ProductKey = entity.ProductUrl });
                }

                //TODO: Change the Object Name (PV) according to the Naming Convention Document. No Shorthand object name is allowed --> Tutul
                //Save product visiting details
                if (LoggedInUser != null && LoggedInUser.Company != null && LoggedInUser.Company.ID != entity.CompanyID)
                {
                    ProductVisitDetail PV = new ProductVisitDetail();
                    PV.ProductID = productID.ToInt();
                    PV.VisitedDate = System.DateTime.Now;
                    PV.UserId = (LoggedInUser == null) ? 0 : LoggedInUser.ID;

                    _Context.AddToProductVisitDetails(PV);
                    _Context.SaveChanges();
                }
                //End saving

                product = Mapper.Map<ProductViewModel>(entity);
                WebUtil.MapZGL(product, entity.Category.PropertyDefinition);
            }
            return View("~/Views/Product/Details.cshtml", product);            
        }
        #endregion Action Methods of Company

        #region Helper Methods

        private void sendActivationNotification(Company company, Contact contact)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            if (template.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                //sb.AppendFormat("Dear Admin,<br/>");
                sb.AppendFormat("Thank you for registering in {0}. Click on the link below to activate your account.<br /><br />", ConfigReader.SiteName);
                sb.AppendFormat("<a href='{0}/Company/Activate?ID={1}&Key={2}'>{0}/Company/Activate?ID={1}&Key={2}</a><br /><br />", WebUtil.GetDomainAddress(),
                    company.ID, company.ActivationKey.ToString());
                sb.AppendFormat("<b>Note:</b> If you cannot click on the link then Copy it and Paste to your browser's address bar to make your account active.");
                ///Proejct Details
                //sb.Append("<br /><br />");
                template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
                template.Replace(AppConstants.ETConstants.MESSAGE, sb.ToString());
                String fromEmail = ConfigReader.SupportEmail;
                String toEmail = String.Empty;//ConfigReader.AdminEmail;
                if (!contact.EmailOffice.IsEmpty())
                    toEmail = contact.EmailOffice;
                else if (!contact.EmailPersonal.IsEmpty())
                    toEmail = contact.EmailPersonal;
                
                String subject = String.Format("Activate your account in {0}.", ConfigReader.SiteName);
                WebUtil.SendMail(fromEmail, toEmail, String.Empty, String.Empty, subject, template.ToString());
            }
        }
        private void sendAdminNotification(Company company)
        {
            StringBuilder template = new StringBuilder(WebUtil.ReadEmailTemplate(AppConstants.EmailTemplate.COMMON));
            if (template.Length > 0)
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("Dear Admin,<br/>");
                sb.AppendFormat("A new company has been registerd in {0}. Click on the link below to see details.<br /><br />", ConfigReader.SiteName);
                sb.AppendFormat("<a href='{0}/{1}'>{0}/{1}</a><br /><br />", WebUtil.GetDomainAddress(),
                    company.Name.ToSeoUrl());

                //sb.AppendFormat("<a href='{0}/Company/Profile/{1}/{2}'>{0}/Company/Profile/{1}/{2}</a><br /><br />", WebUtil.GetDomainAddress(),
                //    company.ID, company.Name.ToSeoUrl());
                ////sb.AppendFormat("<b>Note:</b> If you cannot click on the link then Copy it and Paste to your browser's address bar to make your account active.");
                ///Proejct Details
                //sb.Append("<br /><br />");
                template.Replace(AppConstants.ETConstants.DOMAIN, WebUtil.GetDomainAddress());
                template.Replace(AppConstants.ETConstants.MESSAGE, sb.ToString());
                String fromEmail = ConfigReader.SupportEmail;
                String toEmail = ConfigReader.AdminEmail;            

                String subject = String.Format("New Company Registered in {0}.", ConfigReader.SiteName);
                WebUtil.SendMail(fromEmail, toEmail, String.Empty, String.Empty, subject, template.ToString());
            }
        }

        public ActionResult Activate(String id, String key)
        {
            if (id.IsNullOrEmpty() && key.IsNullOrEmpty())
                ModelState.AddModelError(AppConstants.Validation.WRONG_ACTIVATION_REQUEST, "Invalid Request.");
            else
            {
                Guid activationKey = Guid.Empty;
                Guid.TryParse(key, out activationKey);
                int companyID = id.ToInt();
                Company companry = _Context.Companies.FirstOrDefault(P => P.ActivationKey == activationKey && P.ID == companyID);
                if (companry == null)
                    ModelState.AddModelError(AppConstants.Validation.WRONG_ACTIVATION_REQUEST, "Invalid Request.");
                else
                {
                    if (companry.IsActive)                    
                        ModelState.AddModelError(AppConstants.Validation.WRONG_ACTIVATION_REQUEST, "This company is already activated.");                    
                    else
                    {
                        companry.IsActive = true;
                        var users = from P in _Context.UserContacts where P.Contact.CompanyID == companry.ID select P.User;
                        foreach (User user in users)
                        {
                            user.IsActive = true;
                        }
                        _Context.SaveChanges();
                        ViewData[AppConstants.ViewDataKeys.HAS_ACTIVATED] = true;
                    }
                }
            }
            return View();
        }
        #endregion			
    }
}
